home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / procssng / ccs / ccs-11tl.lha / lbl / xview / genial / func / histo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-14  |  25.1 KB  |  1,010 lines

  1. /*
  2.  * histo.c -- routines for finding histograms in subregions of an image
  3.  *
  4.  */
  5.  
  6. #include <math.h>
  7. #include "display.h"
  8. #include "common.h"
  9. #include "ui.h"
  10. #include "log.h"
  11. #include "reg.h"
  12. #include "histo_ui.h"
  13. #include "scale.h"
  14.  
  15. GC        hgc = NULL;
  16.  
  17. struct hcontext *newhist(), *histo_by_win(), *histo_by_panelwin(), *histo_by_lid();
  18.  
  19. int       color_mode;        /* color mode / magnify mode flag */
  20.  
  21. /*********************************************************/
  22. histo_init()
  23. {
  24.     if (histo_ctrl == NULL) {
  25.     histo_ctrl = histo_histo_ctrl_objects_initialize(NULL,
  26.                              base_win->ctrlwin);
  27.         histo_control_init();
  28.     }
  29.     reg_setdom(AREA);
  30.  
  31.     clear_info();
  32.     lab_info("Please select a region for histogram", 1);
  33.     lab_info("Hit <eval> to create histogram.", 2);
  34.  
  35.     return 0;
  36. }
  37.  
  38. /*********************************************************/
  39. histo_eval()
  40. {
  41.     char      title[80];
  42.     struct hcontext *curhist;
  43.     XGCValues gcval;
  44.     XFontStruct *fs;
  45.  
  46.     curhist = newhist();
  47.     xv_set(histo_ctrl->histno,
  48.        PANEL_VALUE, curfunc->id - 1,
  49.        NULL);
  50.     if (hgc == NULL) {
  51.     /* set up a GC for the window */
  52.     gcval.foreground = BlackPixel(display, DefaultScreen(display));
  53.     gcval.background = WhitePixel(display, DefaultScreen(display));
  54.     gcval.clip_mask = None;
  55.     hgc = XCreateGC(display, curhist->hxid,
  56.             GCForeground | GCBackground | GCClipMask, &gcval);
  57.  
  58.     if (!(fs = XLoadQueryFont(display, "9x15"))) {
  59.         fprintf(stderr, "Font 9x15 not found, trying \'fixed\' \n");
  60.         if (!(fs = XLoadQueryFont(display, "fixed"))) {
  61.         fprintf(stderr, "error geting fonts, exitting...\n");
  62.         exit(-1);
  63.         }
  64.     }
  65.     XSetFont(display, hgc, fs->fid);
  66.  
  67.     }
  68.     if (comp_hist(curhist) > 0) {
  69.     sprintf(title, "Histogram: %d", curfunc->id);
  70.     xv_set(curhist->histo_display->display,
  71.            XV_LABEL, title,
  72.            XV_SHOW, TRUE, FRAME_CLOSED, FALSE,
  73.            NULL);
  74.     }
  75.     return 0;
  76. }
  77.  
  78. /*************************************************************/
  79. int
  80. histo_change(id)
  81.     int       id;
  82. {
  83.     struct hcontext *curhist;
  84.  
  85.     printf(" in histo change: .. \n");
  86.  
  87.     curhist = histo_by_lid(id);
  88.     if (curhist == NULL) {
  89.     XBell(display, 0);
  90.     printf("no such histogram!\n");
  91.     return -1;
  92.     }
  93.     if (comp_hist(curhist) > 0) {
  94.     xv_set(curhist->histo_display->display,
  95.            XV_SHOW, TRUE, FRAME_CLOSED, FALSE,
  96.            NULL);
  97.     }
  98.     return 1;
  99. }
  100.  
  101.  
  102. /*************************************************************/
  103. /* routine to find an unused histo context or to allocate a new one if none
  104.    are available */
  105. struct hcontext *
  106. newhist()
  107. {
  108.     struct hcontext *hist;
  109.  
  110.     if (curfunc->hist != NULL)
  111.     free(curfunc->hist);
  112.  
  113.     hist = (struct hcontext *) malloc(sizeof(struct hcontext));
  114.     makehist(hist);
  115.     curfunc->hist = hist;
  116.     return hist;
  117.  
  118. }
  119.  
  120. /**************************************************************/
  121. makehist(ctx)
  122.     struct hcontext *ctx;
  123. {
  124.     int       i;
  125.  
  126.     ctx->histo_display = histo_display_objects_initialize(NULL,
  127.                               base_win->ctrlwin);
  128.     ctx->paintwin = canvas_paint_window(ctx->histo_display->histocanv);
  129.     ctx->hxid = (XID) xv_get(ctx->paintwin, XV_XID, NULL);
  130.     ctx->rtype = getrtype();
  131.  
  132.     for (i = 0; i < NUM_BUCKETS; i++) {
  133.     ctx->countvec[i] = 0;
  134.     ctx->lbtab[i].npts = 0;
  135.     ctx->lbtab[i].asize = 0;
  136.     }
  137.     for (i = 0; i < NUM_SUB; i++) {
  138.     ctx->interval[i].lower = 0;
  139.     ctx->interval[i].upper = NUM_BUCKETS - 1;
  140.     ctx->interval[i].islit = ctx->interval[i].isactive = 0;
  141.     }
  142.     ctx->subnum = 0;
  143.     ctx->minb = 0;
  144.     ctx->maxb = NUM_BUCKETS - 1;
  145.     ctx->pbuf = (XPoint *) malloc(sizeof(XPoint) * BSIZE);
  146.     ctx->pbsize = BSIZE;
  147.     ctx->pblen = 0;
  148.     ctx->xglab = ctx->yglab = NULL;
  149. }
  150.  
  151. /*****************************************/
  152. show_histogram(ctx)        /* for debugging */
  153.     struct hcontext *ctx;
  154. {
  155.     int       i;
  156.  
  157.     for (i = 0; i < NUM_BUCKETS; i++)
  158.     if (ctx->countvec[i] != 0) {
  159.         printf("bucket: %d, count %d, gray value: %d \n",
  160.            i, ctx->countvec[i], btog(i, ctx));
  161.     }
  162. }
  163.  
  164. /*************************************/
  165. histo_clear(id)
  166.     int       id;
  167. {
  168.     int       i;
  169.     struct hcontext *hist;
  170.  
  171. #ifdef DEBUG
  172.     printf("clearing histogram %d \n", id);
  173. #endif
  174.  
  175.     hist = histo_by_lid(id);
  176.     if (hist == NULL) {
  177.     printf("histo_clear: no such histogram! (id=%d)\n", id);
  178.     return -1;
  179.     }
  180.     for (i = 0; i < NUM_SUB; i++) {
  181.     if (hist->interval[i].islit)
  182.         unlite(hist, i);
  183.     }
  184.  
  185.     delhcontext(hist);
  186.  
  187.     if (id == 1) {
  188.     xv_set(histo_ctrl->histo_ctrl,
  189.            FRAME_CMD_PUSHPIN_IN, FALSE, NULL);
  190.     xv_set(histo_ctrl->histo_ctrl,
  191.            XV_SHOW, FALSE,
  192.            NULL);
  193.     }
  194.     return 0;
  195. }
  196.  
  197. /*************************************************************/
  198. histo_reset()
  199. {
  200.     return 0;
  201. }
  202.  
  203. /*************************************************************/
  204. histo_color_opts(item, event)
  205.     Panel_item item;
  206.     Event    *event;
  207. {
  208.     void      restore_proc();
  209.     struct hcontext *hist;
  210.  
  211.     hist = histo_by_panelwin(event_window(event));
  212.     if (hist == NULL)
  213.     return;
  214.  
  215.     if (((int) xv_get(histo_ctrl->histo_ctrl, XV_SHOW, NULL)) == FALSE) {
  216.     xv_set(histo_ctrl->histo_ctrl,
  217.            XV_SHOW, TRUE, FRAME_CLOSED, FALSE, NULL);
  218.     xv_set(histo_ctrl->histo_ctrl,
  219.            FRAME_CMD_PUSHPIN_IN, TRUE, NULL);
  220.     xv_set(hist->histo_display->magnify,
  221.            PANEL_INACTIVE, TRUE,
  222.            NULL);
  223.     xv_set(hist->histo_display->unmagnify,
  224.            PANEL_INACTIVE, TRUE,
  225.            NULL);
  226.         histo_control_init();
  227.     xv_set(histo_ctrl->sel1, PANEL_VALUE, 1, NULL);
  228.     hist->subnum = 0;
  229.     xv_set(histo_ctrl->histno, PANEL_VALUE, (curfunc->id - 1), NULL);
  230.     restore_proc(item, event);
  231.     color_mode = 1;
  232.  
  233.     } else {
  234.     xv_set(histo_ctrl->histo_ctrl,
  235.            FRAME_CMD_PUSHPIN_IN, FALSE, NULL);
  236.     xv_set(histo_ctrl->histo_ctrl, XV_SHOW, FALSE, NULL);
  237.     xv_set(hist->histo_display->magnify,
  238.            PANEL_INACTIVE, FALSE,
  239.            NULL);
  240.     xv_set(hist->histo_display->unmagnify,
  241.            PANEL_INACTIVE, FALSE,
  242.            NULL);
  243.     color_mode = 0;
  244.     hist->subnum = 0;
  245.     }
  246.  
  247.     return;
  248. }
  249.  
  250. /*************************************************************/
  251. /* routine to do the actual computation involved in figuring out what a
  252.    histogram should look like */
  253. /* histogram computation can be a very unpleasant thing.  Since have to do a
  254.    flood_fill, there is no nice way to avoid copying points.  It is, in fact,
  255.    more efficient to copy points to a temporary buffer than it is to recompute
  256.    the flood_fill. And since we have to find the extrema of the gray values
  257.    within the histogram region, we have to make at least two passes over the
  258.    data.  */
  259. int
  260. comp_hist(hist)
  261.     struct hcontext *hist;
  262. {
  263.     /* fill the point buffer based on region type */
  264.     if (fill_pbuf(hist) <= 0) {
  265.     XBell(display, 0);
  266.     fprintf(stderr, "Invalid region! \n");
  267.     return -1;
  268.     }
  269.     /* find extrema of points */
  270.     h_extrema(hist);
  271.     /* fill the actual buckets and lookback table */
  272.     fill_cvec(hist);
  273.     /* and draw it */
  274.     draw_hist(hist);
  275.  
  276.     return 1;
  277. }
  278.  
  279. /*************************************************************/
  280. /*
  281.  * fill_pbuf() -- fills the pbuf structure with points corresponding to the
  282.  * selected region
  283.  */
  284. int
  285. fill_pbuf(hist)
  286.     struct hcontext *hist;
  287. {
  288.     int       rval;
  289.     switch (hist->rtype) {
  290.     case BOX:
  291.     case POLYGON:
  292.     case CLSPLINE:
  293.     rval = flood_fill(curfunc->reg, &hist->pbuf, &hist->pbsize, &hist->pblen);
  294.     break;
  295.     }
  296.     return (rval);
  297. }
  298.  
  299.  
  300.  
  301. /*************************************************************/
  302. draw_hist(hist)
  303.     struct hcontext *hist;
  304. {
  305.     histo_repaint_proc(hist->histo_display->histocanv,
  306.                hist->paintwin, display, hist->hxid, NULL);
  307. }
  308.  
  309. /*************************************************************/
  310. /*
  311.  * h_extrema() -- extrema of the points in a histogram
  312.  *
  313.  */
  314. h_extrema(hist)
  315.     struct hcontext *hist;
  316. {
  317.     int       i;
  318.     u_long    v, max, min;
  319.  
  320.     max = min = getpix(orig_img, hist->pbuf->x, hist->pbuf->y);
  321.     for (i = 0; i < hist->pblen; i++) {
  322.     v = getpix(orig_img, hist->pbuf[i].x, hist->pbuf[i].y);
  323.     if (v < min)
  324.         min = v;
  325.     else if (v > max)
  326.         max = v;
  327.     }
  328.     hist->minv = (int) min;
  329.     hist->maxv = (int) max;
  330.  
  331. #ifdef DEBUG
  332.     printf("gray values: min: %d, max: %d \n", min, max);
  333. #endif
  334. }
  335.  
  336. /*************************************************************/
  337. /* fill_cvec() -- fill the countvec filed in the histogram context structure */
  338. fill_cvec(hist)
  339.     struct hcontext *hist;
  340. {
  341.     int       i, index;
  342.     float     delta;
  343.     unsigned long g;
  344.     char      message[80];
  345.     int       total = 0;
  346.  
  347.     delta = (float) (NUM_BUCKETS - 1) / (float) (hist->maxv - hist->minv);
  348.     for (i = 0; i < hist->pblen; i++) {
  349.     g = getpix(orig_img, hist->pbuf[i].x, hist->pbuf[i].y);
  350.     /*
  351.      * not using gtob() here because faster to put delta computation out
  352.      * of the loop
  353.      */
  354.     index = (int) (((g - hist->minv) * delta) + .5);
  355.     if (index >= NUM_BUCKETS)
  356.         index = NUM_BUCKETS - 1;
  357.     lbtab_add(hist, index, hist->pbuf + i);
  358.     hist->countvec[index]++;
  359.     if (hist->countvec[index] > hist->maxc)
  360.         hist->maxc = hist->countvec[index];
  361.     }
  362.     if (delta == 1) {
  363.     hist->minb = 0;
  364.     hist->maxb = hist->maxv - hist->minv;
  365.     }
  366.     for (i = 0; i < NUM_BUCKETS; i++)
  367.     total += (btog(i, hist) * hist->countvec[i]);
  368.  
  369.     sprintf(message, "Total Intensity: %d", total);
  370.     xv_set(hist->histo_display->message5,
  371.        PANEL_LABEL_STRING, message, NULL);
  372.     panel_paint(hist->histo_display->message5, PANEL_CLEAR);
  373. }
  374.  
  375. /*************************************************************/
  376. lbtab_add(hist, i, pt)
  377.     struct hcontext *hist;
  378.     int       i;
  379.     XPoint   *pt;
  380. {
  381.     struct lbent *lb;
  382.  
  383.     lb = hist->lbtab + i;
  384.     if (lb->npts >= lb->asize) {
  385.     if (lb->asize == 0) {
  386.         lb->asize = BSIZE;
  387.         lb->parr = (XPoint *) malloc(lb->asize * sizeof(XPoint));
  388.     } else {
  389.         lb->asize += BSIZE;    /* increase size in increments of BSIZE */
  390.         lb->parr = (XPoint *) realloc(lb->parr, lb->asize * sizeof(XPoint));
  391.     }
  392.     }
  393.     lb->parr[lb->npts].x = pt->x;
  394.     lb->parr[lb->npts].y = pt->y;
  395.     (lb->npts)++;
  396. }
  397.  
  398. /***************************************************************/
  399. /*
  400.  * Repaint callback function for `histocanv'.
  401.  */
  402. histo_repaint_proc(canvas, paint_window, display, xid, rects)
  403.     Canvas    canvas;
  404.     Xv_window paint_window;
  405.     Display  *display;
  406.     Window    xid;
  407.     Xv_xrectlist *rects;
  408. {
  409.     struct hcontext *hist;
  410.     int       shmin, shmax;    /* horizontal and vertical scaling, max and
  411.                  * min */
  412.     XGCValues gcval;
  413.     XPoint    src;
  414.     double    xdelt, ydelt, xtmp;
  415.     struct graph_lab *xglab, *yglab;
  416.     char      message[80];
  417.     int       xlen, ylen, i, wid, hgt;
  418.  
  419.     fputs("histo: histo_repaint_proc\n", stderr);
  420. #ifdef DEBUG
  421. #endif
  422.  
  423.     hist = histo_by_win(paint_window);
  424.     if (hist == NULL) {
  425.     fprintf(stderr, "histogram window not found \n");
  426.     return;
  427.     }
  428.     if (hist->pblen == 0)
  429.     return;
  430.  
  431.     XClearWindow(display, xid);
  432.     gcval.foreground = BlackPixel((Display *) display,
  433.                   DefaultScreen((Display *) display));
  434.     XChangeGC(display, hgc, GCForeground, &gcval);
  435.     XDrawRectangle(display, xid, hgc, SX, SY, GRWIDTH, GRHGT);
  436.  
  437.     shmin = btog(hist->minb, hist);
  438.     shmax = btog(hist->maxb, hist);
  439.     /* label the graph */
  440.     if (hist->xglab != NULL) {
  441.     free(hist->xglab);
  442.     free(hist->yglab);
  443.     }
  444.     /* find the min and max gray value counts for this histogram */
  445.     hist->maxc = c_max(hist->minb, hist->maxb, hist);
  446.     hist->minc = c_min(hist->minb, hist->maxb, hist);
  447.     xlen = build_glab(shmin, shmax, 10, GRWIDTH, &xglab);
  448.     xlabelgraph(display, xid, hgc, xglab, xlen, SX, SY + GRHGT,
  449.         GRWIDTH, GRHGT, HORIZONTAL, 1);
  450.  
  451. #ifdef STRONGDEBUG
  452.     printf("scaled min:%d max: %d\n", shmin, shmax);
  453.     glab_db(xglab, xlen);
  454. #endif
  455.  
  456.     ylen = build_glab(hist->minc, hist->maxc, 10, GRHGT, &yglab);
  457.     xlabelgraph(display, xid, hgc, yglab, ylen, SX + GRWIDTH, GRHGT + SY,
  458.         GRWIDTH, GRHGT, VERTICAL, -1);
  459.  
  460. #ifdef STRONGDEBUG
  461.     printf("hist->minc=%d hist->maxc==%d\n", hist->minc, hist->maxc);
  462.     glab_db(yglab, ylen);
  463. #endif
  464.  
  465.     hist->xglab = xglab;
  466.     hist->yglab = yglab;
  467.     hist->xglen = xlen;
  468.     hist->yglen = ylen;
  469.  
  470.     xtmp = hist->xglab[hist->xglen - 1].val - hist->xglab[0].val;
  471.     if (xtmp == 0.)
  472.     return;
  473.     xdelt = (float) GRWIDTH / xtmp;
  474.     xtmp = yglab[ylen - 1].val - yglab[0].val;
  475.     if (xtmp == 0.)
  476.     return;
  477.     ydelt = (float) GRHGT / xtmp;
  478.  
  479.     wid = irint(xdelt);
  480.     if (wid < 1)
  481.     wid = 1;
  482.     for (i = hist->minb; i < hist->maxb; i++) {
  483.     if (i >= NUM_BUCKETS) {
  484.         fprintf(stderr, "Histogram error!! \n");
  485.         exit(0);
  486.     }
  487.     hgt = irint((double) hist->countvec[i] * ydelt);
  488.     src.x = (short) btox(i, hist);
  489.     src.y = (short) GRHGT - hgt + SY;
  490. #ifdef STRONGDEBUG
  491.     printf("Rectangle: gray value %d, count: %d at: (%d,%d), width:%d, height: %d\n", btog(i, hist), hist->countvec[i], src.x, src.y, wid, hgt);
  492. #endif
  493.     XFillRectangle(display, xid, hgc, src.x, src.y, wid, hgt);
  494.     }
  495.  
  496.     draw_histo_color_lines(hist);
  497.  
  498.     sprintf(message, "Pixel Value:   ");
  499.     xv_set(hist->histo_display->message1,
  500.        PANEL_LABEL_STRING, message, NULL);
  501.     sprintf(message, "Pixel Count:   ");
  502.     xv_set(hist->histo_display->message2,
  503.        PANEL_LABEL_STRING, message, NULL);
  504.     panel_paint(hist->histo_display->message1, PANEL_CLEAR);
  505.     panel_paint(hist->histo_display->message2, PANEL_CLEAR);
  506.  
  507. }
  508.  
  509. /*******************************************************************/
  510.  
  511. struct hcontext
  512.          *
  513. histo_by_win(win)
  514.     Xv_Window win;
  515. {
  516.     struct hcontext *hist;
  517.     struct logent *log;
  518.  
  519.     log = loghead;
  520.     while (log != NULL) {
  521.     hist = log->hist;
  522.     if (hist != NULL) {
  523.         if (hist->paintwin == win)
  524.         return hist;
  525.     }
  526.     log = log->next;
  527.     }
  528.     printf("histo_by_win: No such histogram window!\n");
  529.     return NULL;
  530. }
  531.  
  532. /*****************************************************************/
  533. struct hcontext *
  534. histo_by_panelwin(win)
  535.     Xv_Window win;
  536. {
  537.     struct hcontext *hist;
  538.     struct logent *log;
  539.  
  540.     log = loghead;
  541.     while (log != NULL) {
  542.     hist = log->hist;
  543.     if (hist != NULL) {
  544.         if (hist->histo_display->controls2 == win)
  545.         return hist;
  546.     }
  547.     log = log->next;
  548.     }
  549.     printf("histo_by_panelwin: No such histogram window!\n");
  550.     return NULL;
  551. }
  552.  
  553.  
  554. /*****************************************************************/
  555. struct hcontext *
  556. histo_by_lid(id)
  557.     int       id;
  558. {
  559.     struct logent *log;
  560.  
  561.     log = loghead;
  562.     while (log != NULL) {
  563.     if (log->id == id)
  564.         return (log->hist);
  565.     log = log->next;
  566.     }
  567.     return NULL;
  568. }
  569.  
  570. /*******************************************************************/
  571. /*
  572.  * Event callback function for `histocanv'.
  573.  */
  574. Notify_value
  575. histo_event_proc(win, event, arg, type)
  576.     Xv_window win;
  577.     Event    *event;
  578.     Notify_arg arg;
  579.     Notify_event_type type;
  580. {
  581.     struct hcontext *hist;
  582.     int       buckval, lastbuck, x;
  583.     float     xdelt;
  584.     char      message[80];
  585.  
  586.     if (!(event_is_down(event)))
  587.     return notify_next_event_func(win, (Notify_event) event, arg, type);
  588.     if (event_id(event) != BUT(1) && event_id(event) != BUT(3))
  589.     return notify_next_event_func(win, (Notify_event) event, arg, type);
  590.  
  591. #ifdef DEBUG
  592.     fprintf(stderr, "histo: histo_event_proc: event %d\n", event_id(event));
  593. #endif
  594.  
  595.     hist = histo_by_win(win);
  596.     if (hist == NULL)
  597.     return notify_next_event_func(win, (Notify_event) event, arg, type);
  598.  
  599.     x = event_x(event);
  600.     if ((x <= SX) || (x >= GRWIDTH + SX)) {
  601.     return notify_next_event_func(win, (Notify_event) event, arg, type);
  602.     }
  603.     /* find the bucket corresponding with the event */
  604.     xdelt = (float) GRWIDTH / (hist->xglab[hist->xglen - 1].val -
  605.                    hist->xglab[0].val);
  606.     /* assume line is centered in rectangle */
  607.     x = x - (int) ((.5 * xdelt) + .5);
  608.     buckval = xtob(x, hist);
  609.  
  610.     /* set the panel labels appropriately */
  611.     sprintf(message, "Pixel Value: %d", btog(buckval, hist));
  612.     xv_set(hist->histo_display->message1,
  613.        PANEL_LABEL_STRING, message, NULL);
  614.     sprintf(message, "Pixel Count: %d", hist->countvec[buckval]);
  615.     xv_set(hist->histo_display->message2,
  616.        PANEL_LABEL_STRING, message, NULL);
  617.     panel_paint(hist->histo_display->message1, PANEL_CLEAR);
  618.     panel_paint(hist->histo_display->message2, PANEL_CLEAR);
  619.  
  620.  
  621. #ifdef STRONGDEBUG
  622.     show_histogram(hist);
  623. #endif
  624.  
  625.     if (event_id(event) == BUT(1)) {
  626.     if (buckval < hist->interval[hist->subnum].upper) {
  627.         hist->interval[hist->subnum].isactive = 1;
  628.         lastbuck = hist->interval[hist->subnum].lower;
  629.         hist->interval[hist->subnum].lower = buckval;    /* set value */
  630.         histo_line_draw(hist, buckval, lastbuck, TRUE);
  631.     }
  632.     }
  633.     if (event_id(event) == BUT(3)) {
  634.     if (buckval > hist->interval[hist->subnum].lower) {
  635.         hist->interval[hist->subnum].isactive = 1;
  636.         lastbuck = hist->interval[hist->subnum].upper;
  637.         hist->interval[hist->subnum].upper = buckval;    /* set value */
  638.         histo_line_draw(hist, buckval, lastbuck, FALSE);
  639.     }
  640.     }
  641.     return notify_next_event_func(win, (Notify_event) event, arg, type);
  642. }
  643.  
  644. /*************************************************/
  645. histo_line_draw(hist, buckval, lastbuck, lower)
  646.     struct hcontext *hist;
  647.     int       buckval, lastbuck, lower;
  648. {
  649.  
  650.     /* first un-draw red line with a background-color line */
  651. #ifdef DEBUG
  652.     printf("histo_line_draw: repainting bucket %d\n", lastbuck);
  653. #endif
  654.  
  655.     undraw_histo_line(hist, lastbuck);
  656.  
  657.     /* redraw all color lines */
  658.     draw_histo_color_lines(hist);
  659.  
  660.     if (color_mode) {
  661.     if (hist->subnum == 0) {
  662.         if (lower)
  663.         xv_set(histo_ctrl->min1, PANEL_VALUE, btog(buckval, hist), NULL);
  664.         else
  665.         xv_set(histo_ctrl->max1, PANEL_VALUE, btog(buckval, hist), NULL);
  666.     }
  667.     if (hist->subnum == 1) {
  668.         if (lower)
  669.         xv_set(histo_ctrl->min2, PANEL_VALUE, btog(buckval, hist), NULL);
  670.         else
  671.         xv_set(histo_ctrl->max2, PANEL_VALUE, btog(buckval, hist), NULL);
  672.     }
  673.     if (hist->subnum == 2) {
  674.         if (lower)
  675.         xv_set(histo_ctrl->min3, PANEL_VALUE, btog(buckval, hist), NULL);
  676.         else
  677.         xv_set(histo_ctrl->max3, PANEL_VALUE, btog(buckval, hist), NULL);
  678.     }
  679.     if (hist->subnum == 3) {
  680.         if (lower)
  681.         xv_set(histo_ctrl->min4, PANEL_VALUE, btog(buckval, hist), NULL);
  682.         else
  683.         xv_set(histo_ctrl->max4, PANEL_VALUE, btog(buckval, hist), NULL);
  684.     }
  685.     if (hist->subnum == 4) {
  686.         if (lower)
  687.         xv_set(histo_ctrl->min5, PANEL_VALUE, btog(buckval, hist), NULL);
  688.         else
  689.         xv_set(histo_ctrl->max5, PANEL_VALUE, btog(buckval, hist), NULL);
  690.     }
  691.     if (hist->subnum == 5) {
  692.         if (lower)
  693.         xv_set(histo_ctrl->min6, PANEL_VALUE, btog(buckval, hist), NULL);
  694.         else
  695.         xv_set(histo_ctrl->max6, PANEL_VALUE, btog(buckval, hist), NULL);
  696.     }
  697.     if (hist->subnum == 6) {
  698.         if (lower)
  699.         xv_set(histo_ctrl->min7, PANEL_VALUE, btog(buckval, hist), NULL);
  700.         else
  701.         xv_set(histo_ctrl->max7, PANEL_VALUE, btog(buckval, hist), NULL);
  702.     }
  703.     if (hist->subnum == 7) {
  704.         if (lower)
  705.         xv_set(histo_ctrl->min8, PANEL_VALUE, btog(buckval, hist), NULL);
  706.         else
  707.         xv_set(histo_ctrl->max8, PANEL_VALUE, btog(buckval, hist), NULL);
  708.     }
  709.     }
  710. }
  711.  
  712. /***************************************************************/
  713. undraw_histo_line(hist, lastbuck)
  714.     struct hcontext *hist;
  715.     int       lastbuck;
  716. {
  717.     int       oldx, hgt, sy, ey;
  718.     float     xdelt, ydelt;
  719.     XGCValues gcval;
  720.  
  721.     oldx = btox(lastbuck, hist);
  722.     xdelt = (float) GRWIDTH / (hist->xglab[hist->xglen - 1].val -
  723.                    hist->xglab[0].val);
  724.     oldx = oldx + (int) ((.5 * xdelt) + .5);    /* center line in rectangle */
  725.  
  726.  
  727.     gcval.foreground = WhitePixel((Display *) display,
  728.                   DefaultScreen((Display *) display));
  729.     XChangeGC(display, hgc, GCForeground, &gcval);
  730.  
  731.     XSetLineAttributes(display, hgc, 2, LineSolid, CapButt, JoinBevel);
  732.  
  733.     sy = SY + 1;        /* dont overwrite axes */
  734.     ey = SY + GRHGT - 1;
  735. #ifdef DEBUG
  736.     printf("\nRedrawing white line from: (%d,%d) to (%d,%d)\n", oldx, sy,
  737.        oldx, ey);
  738. #endif
  739.  
  740.     if (oldx > SX && oldx < SX + GRWIDTH)    /* dont overwrite axis */
  741.     XDrawLine(display, hist->hxid, hgc, oldx, sy,
  742.           oldx, ey);
  743.  
  744.     /*
  745.      * second, draw black line at same location the same height as the graph
  746.      * line
  747.      */
  748.     gcval.foreground = BlackPixel((Display *) display,
  749.                   DefaultScreen((Display *) display));
  750.     XChangeGC(display, hgc, GCForeground, &gcval);
  751.  
  752.     ydelt = (float) GRHGT / (hist->yglab[hist->yglen - 1].val -
  753.                  hist->yglab[0].val);
  754.     hgt = irint((double) hist->countvec[lastbuck] * ydelt);
  755.     ey = GRHGT + SY;
  756.     sy = ey - hgt;
  757.  
  758.     XDrawLine(display, hist->hxid, hgc, oldx, sy, oldx, ey);
  759.  
  760. #ifdef DEBUG
  761.     printf("Redrawing black line from: (%d,%d) to (%d,%d)\n",
  762.        oldx, sy, oldx, ey);
  763. #endif
  764. }
  765.  
  766. /*************************************************/
  767. /*
  768.  * Notify callback function for `magnify'.
  769.  */
  770. void
  771. mag_proc(item, event)
  772.     Panel_item item;
  773.     Event    *event;
  774. {
  775.     struct hcontext *hist;
  776.  
  777.     hist = histo_by_panelwin(event_window(event));
  778.     if (hist == NULL) {
  779.     printf("No histogram to magnify!\n");
  780.     return;
  781.     }
  782.     if (hist->interval[hist->subnum].lower == 0 &&
  783.     hist->interval[hist->subnum].upper == NUM_BUCKETS - 1) {
  784.     /* dont magnify! */
  785.     return;
  786.     }
  787.     if (hist->subnum < 5) {
  788.     /* set the current display to be within the subrange */
  789.     hist->minb = hist->interval[hist->subnum].lower;
  790.     hist->maxb = hist->interval[hist->subnum].upper;
  791.     hist->subnum++;
  792.     }
  793.     draw_hist(hist);
  794. #ifdef DEBUG
  795.     fputs("histo: mag_proc\n", stderr);
  796. #endif
  797. }
  798.  
  799. /*
  800.  * Notify callback function for `unmagnify'.
  801.  */
  802. void
  803. unmag_proc(item, event)
  804.     Panel_item item;
  805.     Event    *event;
  806. {
  807.     struct hcontext *hist;
  808.  
  809.     hist = histo_by_panelwin(event_window(event));
  810.     if (hist == NULL) {
  811.     printf("No histogram to unmagnify!\n");
  812.     return;
  813.     }
  814.     /* set the current display to be within the subrange */
  815.     if (hist->subnum > 0)
  816.     hist->subnum--;
  817.     if (hist->subnum > 0) {
  818.     hist->minb = hist->interval[hist->subnum - 1].lower;
  819.     hist->maxb = hist->interval[hist->subnum - 1].upper;
  820.     } else {
  821.     hist->minb = 0;
  822.     hist->maxb = NUM_BUCKETS - 1;
  823.     }
  824.  
  825.  
  826.     draw_hist(hist);
  827. #ifdef DEBUG
  828.     fputs("histo: unmag_proc\n", stderr);
  829. #endif
  830. }
  831.  
  832. /*
  833.  * Notify callback function for `restore'.
  834.  */
  835. void
  836. restore_proc(item, event)
  837.     Panel_item item;
  838.     Event    *event;
  839. {
  840.     struct hcontext *hist;
  841.     int       i;
  842.  
  843.     hist = histo_by_panelwin(event_window(event));
  844.     if (hist == NULL) {
  845.     printf("No histogram to restore!\n");
  846.     return;
  847.     }
  848.     /* loop through all intervals and unlite them if lit */
  849.     for (i = 0; i < 5; i++) {
  850.     if (hist->interval[i].islit == 1)
  851.         unlite(hist, i);
  852.     hist->interval[i].isactive = 0;
  853.     hist->interval[i].lower = 0;
  854.     hist->interval[i].upper = NUM_BUCKETS - 1;
  855.     }
  856.     hist->minb = 0;
  857.     hist->maxb = NUM_BUCKETS - 1;
  858.     hist->subnum = 0;
  859.     draw_hist(hist);
  860.     draw_log();
  861. #ifdef DEBUG
  862.     fputs("histo: restore_proc\n", stderr);
  863. #endif
  864. }
  865.  
  866.  
  867. /*******************************************************************/
  868. /* btog() -- bucket # to gray value */
  869. int
  870. btog(b, hist)
  871.     int       b;
  872.     struct hcontext *hist;
  873. {
  874.     float     g;
  875.  
  876.     g = (((float) (b * (hist->maxv - hist->minv))) / NUM_BUCKETS)
  877.     + hist->minv;
  878.  
  879.     return ((int) (g + .5));
  880. }
  881.  
  882. /*************************************************************/
  883. /* btox() -- bucket # to X-coordinate */
  884. int
  885. btox(b, hist)
  886.     int       b;
  887.     struct hcontext *hist;
  888. {
  889.     float     x;
  890.     float     xdelt;        /* width per gray level */
  891.  
  892.     xdelt = (float) GRWIDTH / (hist->xglab[hist->xglen - 1].val - hist->xglab[0].val);
  893.     x = ((float) ((btog(b, hist) - hist->xglab[0].val)) * xdelt) + SX;
  894.  
  895.     return ((int) (x + .5));
  896. }
  897.  
  898. /*************************************************************/
  899. /* gtob() -- gray value to bukcet # */
  900. int
  901. gtob(g, hist)
  902.     int       g;
  903.     struct hcontext *hist;
  904. {
  905.     int       b;
  906.     float     delta;
  907.  
  908.     delta = (float) (NUM_BUCKETS - 1) / (float) (hist->maxv - hist->minv);
  909.     b = (int) (((g - hist->minv) * delta) + .5);
  910.     if (b < 0)
  911.     b = 0;
  912.     if (b >= NUM_BUCKETS)
  913.     b = NUM_BUCKETS - 1;
  914.  
  915. #ifdef DEBUG
  916.     printf("gtob: gray value: %d bucket: %d\n", g, b);
  917. #endif
  918.     return (b);
  919. }
  920.  
  921. /*************************************************************/
  922. /* xtob() -- X-coordinate to bucket # */
  923. int
  924. xtob(x, hist)
  925.     int       x;
  926.     struct hcontext *hist;
  927. {
  928.     int       b, g;        /* bucket, gray value */
  929.  
  930.     g = xtog(x, hist);
  931.     b = gtob(g, hist);
  932.  
  933.     if (b >= NUM_BUCKETS)
  934.     b = NUM_BUCKETS - 1;
  935.     else if (b < 0)
  936.     b = 0;
  937.  
  938. #ifdef DEBUG
  939.     printf("xtob: x: %d, gray value: %d bucket: %d\n", x, g, b);
  940. #endif
  941.     return b;
  942. }
  943.  
  944. /*************************************************************/
  945. int
  946. xtog(x, hist)
  947.     int       x;
  948.     struct hcontext *hist;
  949. {
  950.     float     g;
  951.     int       range;
  952.  
  953.     range = hist->xglab[hist->xglen - 1].val - hist->xglab[0].val;
  954.  
  955.     g = (((float) (x - SX) * range) / (float) GRWIDTH) +
  956.     hist->xglab[0].val;
  957.  
  958. #ifdef DEBUG
  959.     printf("xtog: x: %d, gray value: %d \n", x, (int) (g + .5));
  960. #endif
  961.  
  962.     return ((int) (g + .5));
  963.  
  964. }
  965.  
  966.  
  967. /*************************************************************/
  968. /* routine to find the max count in a histogram */
  969. int
  970. c_max(minb, maxb, hist)
  971.     int       minb, maxb;
  972.     struct hcontext *hist;
  973. {
  974.     int       i, max = 0;
  975.  
  976.     for (i = minb; i <= maxb; i++) {
  977.     if (hist->countvec[i] > max)
  978.         max = hist->countvec[i];
  979.     }
  980.     return max;
  981. }
  982.  
  983. /*************************************************************/
  984. /* routine to find the min count in a histogram */
  985. /* note that this functions depends on hist->maxc holding the correct value */
  986. int
  987. c_min(minb, maxb, hist)
  988.     int       minb, maxb;
  989.     struct hcontext *hist;
  990. {
  991.     int       i, min = hist->maxc;
  992.  
  993.     for (i = minb; i <= maxb; i++) {
  994.     if (hist->countvec[i] < min)
  995.         min = hist->countvec[i];
  996.     }
  997.     return min;
  998. }
  999.  
  1000. /*************************************************************/
  1001. delhcontext(h)
  1002.     struct hcontext *h;
  1003. {
  1004.     xv_set(h->histo_display->display,
  1005.        XV_SHOW, FALSE,
  1006.        NULL);
  1007.  
  1008.     free(h->pbuf);
  1009. }
  1010.